﻿using Newtonsoft.Json;
using S7.Net;
using S7.Net.Types;
using SqlSugar;
using SqlSugar.Extensions;
using Sunny.UI;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using WCS.Controls.RunLog;
using WCS.Entity;
using WCS.Entity.MES;
using WCS.Entity.SYS;
using WCS.Helpers.PLCOperation;
using WCS.Utils;
using WCS.WebRequest;
using WcsTask;

namespace WCS.Helpers
{
    public class PlcDev
    {
        private static PlcDev plcDev = null;

        private static object plcLock = new object();

        public static PlcDev _plcDev
        {
            get
            {
                if (plcDev == null)
                {
                    lock (plcLock)
                    {
                        if (plcDev == null)
                        {
                            plcDev = new PlcDev();
                        }
                    }
                }
                return plcDev;
            }
        }

        /// <summary>
        /// 堆垛机站台集合
        /// </summary>
        public List<StackerStation> StackerStationList = new List<StackerStation>();

        /// <summary>
        /// 输送线站台集合
        /// </summary>
        public List<ConveyorStation> ConveyorStationList = new List<ConveyorStation>();

        /// <summary>
        /// 数据库连接对象
        /// </summary>
        static SqlSugarDapper _SqlSugarDapper = SqlSugarDapper.GetDbContext();

        /// <summary>
        /// 仿真模式
        /// </summary>
        string _simulation = ConfigurationManager.AppSettings["simulation"];
        string postTime = ConfigurationManager.AppSettings["postTime"];

        /// <summary>
        /// PLC连接协议类型
        /// </summary>
        int _PlcContentType = Convert.ToInt32(ConfigurationManager.AppSettings["PlcContentType"]);

        /// <summary>
        /// PLC集合
        /// </summary>
        public List<WcsDevPlc> wcsDevPlcList = new List<WcsDevPlc>();

        /// <summary>
        /// 站台集合
        /// </summary>
        public List<WcsReadTrayCode> wcsReadTrayCodeList = new List<WcsReadTrayCode>();

        /// <summary>
        /// 温度
        /// </summary>
        public List<string> _Temperature = new List<string>();

        /// <summary>
        /// 湿度
        /// </summary>
        public List<string> _Humidity = new List<string>();

        /// <summary>
        /// 温度，湿度
        /// </summary>
        WarehouseInfo _warehouseInfoTH = new WarehouseInfo();

        /// <summary>
        /// 出库条码
        /// </summary>
        WcsReadTrayCode _readOutTrayCode = new WcsReadTrayCode();

        /// <summary>
        /// PLC信号
        /// </summary>
        public ConveyorReadData conveyorReadData = new ConveyorReadData();

        Warehouse warehouse = new Warehouse();

        public S7Plc s7Plc = null;
        /// <summary>
        /// 日志模块
        /// </summary>
        string _modular = "【PLC设备模块】";

        public bool _flag;

        public List<PlcError> plcErrors = new List<PlcError>();

        /// <summary>
        /// 初始化PLC信息
        /// </summary>
        public void Init()
        {
            plcErrors = _SqlSugarDapper.DB.Queryable<PlcError>().ToList();

            Connect();

            PlcDevinit();

            Task.Run(() => ReadDevStationState());

            Task.Run(() => ReadTempHum());

            Task.Run(() => PostTempHum());
        }

        /// <summary>
        /// 初始化PLC站台信息
        /// </summary>
        public void PlcDevinit()
        {
            try
            {
                //获取PLC设备集合
                wcsDevPlcList = _SqlSugarDapper.DB.Queryable<WcsDevPlc>().WhereIF(_simulation == "1", w => w.Enable == "1").ToList();

                foreach (var wcsDevPlc in wcsDevPlcList)
                {
                    if (wcsDevPlc.Dev_Type == Dev_Type.Convey.ToString())
                    {
                        //输送线站台数据初始化
                        wcsDevPlc.conveyStations = _SqlSugarDapper.DB.Queryable<ConveyorStation>().Where(w => w.DevCode == wcsDevPlc.Dev_Code).ToList();

                        //输送线扫码站台数据初始化
                        wcsDevPlc.wcsReadTrayCode = _SqlSugarDapper.DB.Queryable<WcsReadTrayCode>().Where(w => w.Dev_Code == wcsDevPlc.Dev_Code).ToList();

                        wcsReadTrayCodeList.AddRange(wcsDevPlc.wcsReadTrayCode);

                        //遍历输送线站台
                        foreach (var conveyorStation in wcsDevPlc.conveyStations)
                        {
                            //读取地址
                            conveyorStation.ReadAddress = wcsDevPlc.Read_Block + "." + conveyorStation.Station_Read_Offset;
                            if (conveyorStation.Station_Plc_No == "A001")
                            {
                                conveyorStation.ReadAddress = wcsDevPlc.Read_Block + "." + conveyorStation.Station_Read_Offset;
                            }
                            conveyorStation.WriteAddress = wcsDevPlc.Write_Block + "." + conveyorStation.Station_Write_Offset;

                            if (conveyorStation.Station_Plc_No == "A001")
                            {
                                conveyorStation.WriteAddress = wcsDevPlc.Write_Block + "." + conveyorStation.Station_Write_Offset + ".0";
                            }
                            //写入地址
                            //保存对象字典
                            if (ConveyorStationList.Find(c => c.Station_Plc_No == conveyorStation.Station_Plc_No) != null)
                            {
                                RunLog.runLog.Warning($"{_modular}站台【{conveyorStation.Station_Plc_No}】重复配置");
                                return;
                            }
                            ConveyorStationList.Add(conveyorStation);
                        }
                    }

                    if (wcsDevPlc.Dev_Type == Dev_Type.Stacker.ToString())//堆垛机设备
                    {
                        wcsDevPlc.stackerStation = _SqlSugarDapper.DB.Queryable<StackerStation>().Where(w => w.DevCode == wcsDevPlc.Dev_Code).First();

                        if (wcsDevPlc.stackerStation != null)
                        {
                            //读取地址
                            wcsDevPlc.stackerStation.ReadAddress = wcsDevPlc.Read_Block + "." + wcsDevPlc.stackerStation.Station_Read_Offset;
                            //写入地址
                            wcsDevPlc.stackerStation.WriteAddress = wcsDevPlc.Write_Block + "." + wcsDevPlc.stackerStation.Station_Write_Offset;

                            StackerStationList.Add(wcsDevPlc.stackerStation);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                RunLog.runLog.Error($@"{_modular}异常信息【{ex.Message}】【{ex.StackTrace}】");
                throw;
            }

        }

        /// <summary>
        /// 链接PLC
        /// </summary>
        public void Connect()
        {
            try
            {
                //获取PLC设备集合
                var WcsPlcList = _SqlSugarDapper.DB.Queryable<WcsDevPlc>().Where(w => w.Enable == "1").ToList();

                foreach (var item in WcsPlcList)
                {
                    S7Plc plc = new S7Plc(CpuType.S71500, item.Ip);

                    //仿真模式直接返回成功
                    if (_simulation == "0")
                    {
                        //链接PLC
                        var operateResult = plc.ConnectServer();
                        if (operateResult.IsSuccess)
                        {
                            item.S7Plc = plc;
                            s7Plc = plc;
                            RunLog.runLog.Debug($"{_modular}设备IP:{item.Ip}【{item.PLC_Name}】已连接");
                        }
                        else
                        {
                            //链接失败
                            RunLog.runLog.Warning($"{_modular}设备【{item.PLC_Name}】连接失败 【{operateResult.Message}】");
                        }
                    }
                    else
                    {
                        s7Plc = plc;
                    }
                }
            }
            catch (Exception ex)
            {
                RunLog.runLog.Error($@"{_modular}异常信息【{ex.Message}】【{ex.StackTrace}】");
            }
        }

        /// <summary>
        /// byte转Bit
        /// </summary>
        /// <param name="val"></param>
        /// <returns></returns>
        public string Byte_BitToString(byte[] val)
        {
            BitArray bitArray = new BitArray(val);
            string Text = "";

            for (int i = 0; i < bitArray.Count; i++)
            {
                Text += Convert.ToInt32(bitArray[i]);
            }

            return Text;
        }

        /// <summary>
        /// Bit转Byte
        /// </summary>
        /// <param name="bits"></param>
        /// <returns></returns>
        /// <exception cref="ArgumentException"></exception>
        public byte ConvertToByte(BitArray bits)
        {
            if (bits.Count != 8)
            {
                throw new ArgumentException("bits");
            }
            byte[] bytes = new byte[1];
            bits.CopyTo(bytes, 0);
            return bytes[0];
        }

        /// <summary>
        /// 读取设备状态--线程
        /// </summary>
        public void ReadDevStationState()
        {
            while (true)
            {
                foreach (var wcsDevPlc in wcsDevPlcList)
                {
                    //s7Plc.S7PlcWiterString("DB100.6","123");
                    ReadConveyorStationStates(wcsDevPlc);
                }
                Thread.Sleep(500);
            }
        }

        /// <summary>
        /// 读取温度湿度
        /// </summary>
        public void ReadTempHum()
        {
            while (true)
            {
                try
                {
                    S7Plc plc = new S7Plc(CpuType.S7200Smart, "172.12.56.20");

                    var operateResult = plc.ConnectServer();

                    if (operateResult.IsSuccess)
                    {
                        var byteArray = plc.S7PlcRead("DB1.4000.0", 4);
                        var byteArray1 = plc.S7PlcRead("DB1.4004.0", 4);

                        var temp = BitConverter.ToSingle(byteArray.Content.Reverse().ToArray(), 0).ToString("0.0");
                        var hum = BitConverter.ToSingle(byteArray1.Content.Reverse().ToArray(), 0).ToString("0.0");

                        if (_Temperature.Count > 10)
                        {
                            _Temperature.Remove(_Temperature[0]);
                            _Humidity.Remove(_Temperature[0]);
                        }

                        var temperature = (temp.ToFloat() + 2).ToString();
                        var humidity = (hum.ToFloat() - 6).ToString();

                        _Temperature.Add(temperature);
                        _Humidity.Add(humidity);

                        _SqlSugarDapper.DB.Updateable<WcsDevPlc>()
                            .SetColumns(s => s.ATTRIBUTE1 == temperature)
                            .SetColumns(s => s.ATTRIBUTE2 == humidity)
                            .Where(w => w.Dev_Code == "1000").ExecuteCommand();

                        var tem = _SqlSugarDapper.DB.Queryable<WcsDevPlc>()
                              .Where(w => w.PLC_Name == "铸造区").First();

                        if (Convert.ToDouble(tem.ATTRIBUTE1) < Convert.ToDouble(tem.ATTRIBUTE3))
                        {
                            _SqlSugarDapper.DB.Updateable<WcsDevPlc>()
                                .SetColumns(a => a.Remark == $"立库温度过低")
                                .Where(w => w.PLC_Name == "铸造区").ExecuteCommand();
                            _flag = true;
                        }
                        else if (Convert.ToDouble(tem.ATTRIBUTE2) > Convert.ToDouble(tem.ATTRIBUTE4))
                        {
                            _SqlSugarDapper.DB.Updateable<WcsDevPlc>()
                                .SetColumns(a => a.Remark == $"立库湿度过大")
                                .Where(w => w.PLC_Name == "铸造区").ExecuteCommand();
                            _flag = true;

                        }
                        else
                        {
                            _SqlSugarDapper.DB.Updateable<WcsDevPlc>()
                              .SetColumns(a => a.Remark == "")
                              .Where(w => w.PLC_Name == "铸造区").ExecuteCommand();
                            _flag = false;

                        }
                    }
                    #region
                    //Modbus
                    //_modbusTcpNet = new ModbusTcpNet("172.12.56.20");
                    //var s= _modbusTcpNet.ConnectServer();
                    //OperateResult read = _modbusTcpNet.Read("VD4000", 20);
                    //if (read.IsSuccess)
                    //{
                    //    //int temp = _modbusTcpNet.ByteTransform.TransInt32(read.Content, 6);
                    //}

                    //温度
                    //var readBytes = PlcManeger.Read("DB47.782", 256);
                    //if (!readBytes.IsSuccess)
                    //{
                    //    _warehouseInfoTH.TemperatureTop = "0";
                    //}

                    //var codet = readBytes.Content.Take(20).ToArray();
                    //var temperature = Encoding.ASCII.GetString(codet.Skip(2).Take(4).ToArray());
                    //if (codet != null)
                    //{
                    //    _Temperature.Add(temperature);
                    //    //_warehouseInfoTH.TemperatureTop = temperature + "℃";
                    //}

                    ////湿度
                    //readBytes = PlcManeger.Read("DB47.1038", 256);
                    //if (!readBytes.IsSuccess)
                    //{
                    //    _warehouseInfoTH.HumidityTop = "0";
                    //}

                    //var codeh = readBytes.Content.Take(20).ToArray();
                    //var humidity = Encoding.ASCII.GetString(codeh.Skip(2).Take(4).ToArray());
                    //if (codeh != null)
                    //{
                    //    _Humidity.Add(humidity);
                    //    //_warehouseInfoTH.HumidityTop = humidity + "%";
                    //}
                    #endregion

                    Thread.Sleep(30000);
                }
                catch (Exception ex)
                {
                    RunLog.runLog.Error($@"{_modular}异常信息【{ex.Message}】【{ex.StackTrace}】");
                }
            }
        }

        public void PostTempHum()
        {
            while (true)
            {
                try
                {
                    var data = _SqlSugarDapper.DB.Queryable<WcsDevPlc>()
                           .Where(w => w.Dev_Code == "1000").First();

                    long timeStamp = DateTimeOffset.Now.ToUnixTimeSeconds();

                    MesData mesData = new MesData()
                    {
                        uuid = Guid.NewGuid().ToString(),
                        debug = false,
                        uploadTime = timeStamp,
                        machineId = "8103SK00011",
                        dataList = new List<DataList>()
                    };
                    mesData.dataList.Add(new DataList()
                    {
                        param = "Temperature",
                        value = data.ATTRIBUTE1,
                        collectionTime = timeStamp,
                        gatherSpot = "spot1"
                    });
                    mesData.dataList.Add(new DataList()
                    {
                        param = "Humidity",
                        value = data.ATTRIBUTE2,
                        collectionTime = timeStamp,
                        gatherSpot = "spot1"
                    });
                    mesData.dataList.Add(new DataList()
                    {
                        param = "UploadTime",
                        value = System.DateTime.Now.ToString(),
                        collectionTime = timeStamp,
                        gatherSpot = "spot1"
                    });

                    var result = HttpRequest.httpRequest.WebPostRequestMESS(JsonConvert.SerializeObject(mesData), "http://10.3.15.130:8090/apis/datapush/datacollection/dataenv");

                    if (result == null)
                    {
                        RunLog.runLog.Error($@"【温度湿度上报】上传MES失败 MES接口异常");
                        continue;
                    }
                    if (result.ret == 1)
                    {
                        RunLog.runLog.InfoMES($@"【温度湿度上报】上传MES成功 成功信息【{result.data}】温度:{data.ATTRIBUTE1}湿度:{data.ATTRIBUTE2}【JSON】{JsonConvert.SerializeObject(mesData)}");
                    }
                    else
                    {
                        RunLog.runLog.InfoMES($@"【温度湿度上报】上传MES失败 失败信息【{result.data}】【JSON】{JsonConvert.SerializeObject(mesData)}");
                    }
                    Thread.Sleep(3600000);
                }
                catch (Exception ex)
                {
                    RunLog.runLog.Error($@"{_modular}异常信息【{ex.Message}】【{ex.StackTrace}】");
                }
            }
        }

        /// <summary>
        /// 读取输送线设备状态
        /// </summary>
        /// <param name="conveyDev">PLC信息</param>
        public void ReadConveyorStationStates(WcsDevPlc wcsDevPlc)
        {
            try
            {
                //仿真模式
                if (_simulation == "1")
                {
                    conveyorReadData.AllowAOne = true;
                    conveyorReadData.AllowASeven = true;
                    conveyorReadData.GetAOne = true;
                    conveyorReadData.GetASeven = true;
                    conveyorReadData.AllowBOne = true;
                    conveyorReadData.AllowBSeven = true;
                    conveyorReadData.GetBOne = true;
                    conveyorReadData.GetBSeven = true;

                    //#region 处理输送线出库异常任务
                    //读到异常任务号
                    //var abnormalTaskCode = s7Plc.S7PlcReadInt("DB47.364", 2).Content;

                    //var subTask = _SqlSugarDapper.DB.Queryable<WcsTaskConveyor>()
                    //        .Where(w => w.Sub_TaskCode == "7637")
                    //    //.Where(w => w.Sub_TaskCode == abnormalTaskCode.ToString())
                    //    .First();
                    //if (subTask != null)
                    //{
                    //    var localtion = Warehouse.MaterialTypeOutPLCError(1, subTask.MaterialType, subTask.Start_Station);
                    //    if (localtion != null)
                    //    {
                    //        //找到一个可用库存
                    //        /*
                    //            把之前的托盘号状态改为55
                    //            更新任务信息  托盘号loc[0]   出库层数loc[0]  任务状态25
                    //            把当前准备出的托盘状态改为出库占用
                    //            */

                    //        string barCode = localtion[0].barCode;
                    //        string WMSBinCode = localtion[0].ID.Substring(5);
                    //        string Start_Station = localtion[0].ID.Substring(0, 4);
                    //        string End_Station = Start_Station == "9001" ? "B001" : "B007";
                    //        _SqlSugarDapper.DB.BeginTran();
                    //        try
                    //        {
                    //            //把之前的托盘号状态改为55 9001-7
                    //            _SqlSugarDapper.DB.Updateable<WarehouseInfo>()
                    //                .SetColumns(w => w.state == 55)
                    //                .Where(w => w.barCode == subTask.TrayBar_Code)
                    //                .ExecuteCommand();

                    //            //更新子任务信息  托盘号loc[0]   出库层数loc[0]  任务状态25
                    //            _SqlSugarDapper.DB.Updateable<WcsTaskConveyor>()
                    //                .SetColumns(w => w.TrayBar_Code == localtion[0].barCode)
                    //                .SetColumns(w => w.WMSBinCode == WMSBinCode)
                    //                .SetColumns(w => w.Task_State == 25)
                    //                .SetColumns(w => w.Start_Station == Start_Station)
                    //                .SetColumns(w => w.Current_Station == Start_Station)
                    //                .SetColumns(w => w.End_Station == End_Station)
                    //                .Where(w => w.Sub_TaskCode == subTask.Sub_TaskCode)
                    //                .ExecuteCommand();

                    //            //更新主任务信息 
                    //            _SqlSugarDapper.DB.Updateable<WcsTaskMain>()
                    //                .SetColumns(w => w.TrayBar_Code == barCode)
                    //                .SetColumns(w => w.StartWMSBinCode == WMSBinCode)
                    //                .SetColumns(w => w.Start_Station == Start_Station)
                    //                .SetColumns(w => w.Current_Station == Start_Station)
                    //                .SetColumns(w => w.StartWMSBinCode == WMSBinCode)
                    //                .SetColumns(w => w.End_Station == End_Station)
                    //                .Where(w => w.Task_Code == subTask.Task_Code)
                    //                .ExecuteCommand();
                    //            _SqlSugarDapper.DB.CommitTran();

                    //            //把当前准备出的托盘状态改为出库占用
                    //            WarehouseInfo.ChangeWarehouseInfo(localtion[0], (int)StationState.出库占用);

                    //            RunLog.runLog.Warning($@"【输送线任务模块】异常任务号【7637】异常托盘码【{subTask.TrayBar_Code}】重新下发托盘码【{localtion[0].barCode}】");

                    //            //返回PLC 异常任务收到信号
                    //            s7Plc.S7PlcWiterBool("DB48.22.0", (bool)true);
                    //        }
                    //        catch (Exception)
                    //        {
                    //            _SqlSugarDapper.DB.RollbackTran();
                    //        }
                    //    }
                    //}

                    //#endregion
                }

                foreach (var item in _SqlSugarDapper.DB.Queryable<WcsDevStation>().Where(w => w.ATTRIBUTE3 == 1 || w.ATTRIBUTE4 == 1).ToList())
                {
                    if (item.ATTRIBUTE3 == 1)
                    {
                        if (item.Station_Plc_No == "A001" && PlcDev._plcDev.conveyorReadData.AllowAOne == true)
                        {
                            s7Plc.S7PlcWiterBool("DB48.16.0", (bool)true);
                            //PlcManeger.Write("DB48.16.0", (bool)true);
                        }
                        if (item.Station_Plc_No == "A007" && PlcDev._plcDev.conveyorReadData.AllowASeven == true)
                        {
                            s7Plc.S7PlcWiterBool("DB48.16.1", (bool)true);
                        }
                        if (item.Station_Plc_No == "B001" && PlcDev._plcDev.conveyorReadData.AllowBOne == true)
                        {
                            s7Plc.S7PlcWiterBool("DB48.16.2", (bool)true);
                        }
                        if (item.Station_Plc_No == "B007" && PlcDev._plcDev.conveyorReadData.AllowBSeven == true)
                        {
                            s7Plc.S7PlcWiterBool("DB48.16.3", (bool)true);
                        }

                        _SqlSugarDapper.DB.Updateable<ConveyorStation>()
                            .SetColumns(s => s.ATTRIBUTE3 == 0)
                            .Where(w => w.Station_Plc_No == item.Station_Plc_No).ExecuteCommand();
                    }

                    if (item.ATTRIBUTE4 == 1)
                    {
                        if (item.Station_Plc_No == "A001")
                        {
                            s7Plc.S7PlcWiterBool("DB48.16.0", (bool)false);
                            //PlcManeger.Write("DB48.16.0", (bool)false);
                        }
                        if (item.Station_Plc_No == "A007")
                        {
                            s7Plc.S7PlcWiterBool("DB48.16.1", (bool)false);
                        }
                        if (item.Station_Plc_No == "B001")
                        {
                            s7Plc.S7PlcWiterBool("DB48.16.2", (bool)false);
                        }
                        if (item.Station_Plc_No == "B007")
                        {
                            s7Plc.S7PlcWiterBool("DB48.16.3", (bool)false);
                        }

                        _SqlSugarDapper.DB.Updateable<ConveyorStation>()
                            .SetColumns(s => s.ATTRIBUTE4 == 0)
                            .Where(w => w.Station_Plc_No == item.Station_Plc_No).ExecuteCommand();
                    }
                }

                //自动模式
                if (_simulation == "0")
                {
                    #region 读取三个扫码器条码
                    if (!s7Plc.S7PlcReadBool("DB48.20.0").Content)
                    {
                        //读取A002站台条码 条码：81037320063630132  81037320063630045
                        //var readBytesrA001 = PlcManeger.ReadString("DB47.14", Encoding.GetEncoding("gb2312"));
                        var readBytesrA001 = s7Plc.S7PlcReadString("DB47.14");
                        if (readBytesrA001.Content != "" && !readBytesrA001.Content.Contains("NoRead"))
                        {
                            readBytesrA001.Content = readBytesrA001.Content.Substring(0, 17);
                            if (VerifyBarcode(readBytesrA001.Content) || true)
                            {
                                _SqlSugarDapper.DB.Updateable<WcsReadTrayCode>()
                                    .SetColumns(w => w.TrayBar_Code == readBytesrA001.Content)
                                    .Where(w => w.Station_Plc_No == "A002")
                                    .ExecuteCommand();
                                RunLog.runLog.Debug($@"{_modular}读取站台A002读到条码【{readBytesrA001.Content}】");
                            }
                            else
                            {
                                RunLog.runLog.Warning($@"{_modular}读取站台A002读到条码【{readBytesrA001.Content}】此条码已经存在");

                                _SqlSugarDapper.DB.Updateable<WcsReadTrayCode>()
                                    .SetColumns(se => se.Remark == $"【A002号提升机托盘】{readBytesrA001.Content}此条码已经存在")
                                    .Where(w => w.Station_Plc_No == "A002").ExecuteCommand();
                            }

                            s7Plc.S7PlcWiterBool("DB48.20.0", true);
                        }
                    }

                    //读取A006站台条码
                    //var readBytesrA007 = PlcManeger.ReadString("DB47.36", Encoding.GetEncoding("gb2312"));

                    if (!s7Plc.S7PlcReadBool("DB48.20.1").Content)
                    {
                        var readBytesrA007 = s7Plc.S7PlcReadString("DB47.36");
                        if (readBytesrA007.Content != "" && !readBytesrA007.Content.Contains("NoRead"))
                        {
                            readBytesrA007.Content = readBytesrA007.Content.Substring(0, 17);
                            if (VerifyBarcode(readBytesrA007.Content) || true)
                            {
                                _SqlSugarDapper.DB.Updateable<WcsReadTrayCode>()
                                    .SetColumns(w => w.TrayBar_Code == readBytesrA007.Content)
                                    .Where(w => w.Station_Plc_No == "A006")
                                    .ExecuteCommand();
                                RunLog.runLog.Debug($@"{_modular}读取站台A006读到条码【{readBytesrA007.Content}】");
                            }
                            else
                            {
                                RunLog.runLog.Warning($@"{_modular}读取站台A006读到条码【{readBytesrA007.Content}】此条码已经存在");
                                _SqlSugarDapper.DB.Updateable<WcsReadTrayCode>()
                                    .SetColumns(se => se.Remark == $"【A006号提升机托盘】{readBytesrA007.Content}此条码已经存在")
                                    .Where(w => w.Station_Plc_No == "A006").ExecuteCommand();
                            }
                            s7Plc.S7PlcWiterBool("DB48.20.1", true);
                        }
                    }
                    #endregion

                    #region 任务报完成
                    //库口提升机任务报完成
                    var taskOver2009 = s7Plc.S7PlcReadInt("DB47.316", 2);
                    if (taskOver2009.Content != 0)
                    {
                        var Sub_TaskCode = taskOver2009.Content.ToString();
                        if (ConveyorTask._conveyorTask.ConveyTaskFeedbackResult(Sub_TaskCode))
                        {
                            //给PLC反馈确认信号
                            var WriteResult = s7Plc.S7PlcWiter("DB47.316", new byte[2]);
                            if (!WriteResult.IsSuccess)
                            {
                                //更任务的任务提示
                                RunLog.runLog.Warning($"{_modular} 下发任务失败【{Sub_TaskCode}】");
                            }
                        }
                    }
                    //空托入库提升机报完成
                    var taskOver2011 = s7Plc.S7PlcReadInt("DB47.318", 2);
                    if (taskOver2011.Content != 0)
                    {
                        var Sub_TaskCode = taskOver2011.Content.ToString();
                        if (Sub_TaskCode != "0")
                        {
                            if (ConveyorTask._conveyorTask.ConveyTaskFeedbackResult(Sub_TaskCode))
                            {
                                //给PLC反馈确认信号
                                var WriteResult = s7Plc.S7PlcWiter("DB47.318", new byte[2]);
                                if (!WriteResult.IsSuccess)
                                {
                                    RunLog.runLog.Warning($"{_modular} 下发任务失败【{Sub_TaskCode}】");
                                }
                            }
                        }
                    }
                    //B001出货口任务报完成
                    var taskOver2010 = s7Plc.S7PlcReadInt("DB47.320", 2);
                    if (taskOver2010.Content != 0)
                    {
                        var Sub_TaskCode = taskOver2010.Content.ToString();
                        if (Sub_TaskCode != "0")
                        {
                            if (ConveyorTask._conveyorTask.ConveyTaskFeedbackResult(Sub_TaskCode))
                            {
                                //给PLC反馈确认信号
                                var WriteResult = s7Plc.S7PlcWiter("DB47.320", new byte[2]);
                                if (!WriteResult.IsSuccess)
                                {
                                    //更任务的任务提示
                                    RunLog.runLog.Warning($"{_modular} 下发任务失败【{Sub_TaskCode}】");
                                }
                            }
                        }
                    }
                    //B007出货口任务报完成
                    var taskOver2012 = s7Plc.S7PlcReadInt("DB47.322", 2);
                    if (taskOver2012.Content != 0)
                    {
                        var Sub_TaskCode = taskOver2012.Content.ToString();
                        if (Sub_TaskCode != "0")
                        {
                            if (ConveyorTask._conveyorTask.ConveyTaskFeedbackResult(Sub_TaskCode))
                            {
                                //给PLC反馈确认信号
                                var WriteResult = s7Plc.S7PlcWiter("DB47.322", new byte[2]);
                                if (!WriteResult.IsSuccess)
                                {
                                    //更任务的任务提示
                                    RunLog.runLog.Warning($"{_modular} 下发任务失败【{Sub_TaskCode}】");
                                }
                            }
                        }
                    }
                    #endregion

                    #region 十层提升机任务报完成
                    //9001出库口提升机报完成
                    var taskOver9001 = s7Plc.S7PlcReadInt("DB47.366", 2);
                    if (taskOver9001.Content != 0)
                    {
                        var Sub_TaskCode = taskOver9001.Content.ToString();
                        if (ConveyorTask._conveyorTask.ElevatorTaskFeedbackResult(Sub_TaskCode))
                        {
                            //给PLC反馈确认信号
                            var WriteResult = s7Plc.S7PlcWiter("DB47.366", new byte[2]);
                            if (!WriteResult.IsSuccess)
                            {
                                //更任务的任务提示
                                RunLog.runLog.Warning($"{_modular} 下发任务失败【{Sub_TaskCode}】");
                            }
                        }
                    }
                    //9002出库口提升机报完成
                    var taskOver9002 = s7Plc.S7PlcReadInt("DB47.368", 2);
                    if (taskOver9002.Content != 0)
                    {
                        var Sub_TaskCode = taskOver9002.Content.ToString();
                        if (ConveyorTask._conveyorTask.ElevatorTaskFeedbackResult(Sub_TaskCode))
                        {
                            //给PLC反馈确认信号
                            var WriteResult = s7Plc.S7PlcWiter("DB47.368", new byte[2]);
                            if (!WriteResult.IsSuccess)
                            {
                                //更任务的任务提示
                                RunLog.runLog.Warning($"{_modular} 下发任务失败【{Sub_TaskCode}】");
                            }
                        }
                    }
                    #endregion

                    #region 判断A001 A007是否可进入
                    //判断入库口升降机是否可以进入
                    var readBytes = s7Plc.S7PlcRead("DB47.6", 1);
                    var into = Byte_BitToString(readBytes.Content);

                    conveyorReadData.AllowAOne = into[0] == '1';
                    conveyorReadData.AllowASeven = into[1] == '1';
                    #endregion

                    #region 判断 B001 B007是否可进入
                    //读取出库口状态，AGV是否能进入
                    var readBytesB = s7Plc.S7PlcRead("DB47.314", 1);

                    var intoB = Byte_BitToString(readBytesB.Content);
                    conveyorReadData.AllowBOne = intoB[0] == '1';
                    conveyorReadData.AllowBSeven = intoB[1] == '1';

                    #endregion

                    #region 读取PLC出库任务状态

                    readBytes = s7Plc.S7PlcRead("DB47.8", Convert.ToUInt16(1));
                    var pLCState = Byte_BitToString(readBytes.Content);

                    byte[] s = new byte[1];
                    s[0] = 0;
                    if (pLCState[0] == '1')
                    {
                        //清楚PLC出库位置、出库口升降机
                        s7Plc.S7PlcWiter("DB48.6", s);
                        s7Plc.S7PlcWiter("DB48.8", s);
                        //conveyorStation.readData.PlcOutState = true;
                    }

                    #endregion

                    #region 读取PLC---A001 A007是否取完料
                    //读取PLC---A001 A007是否取完料
                    readBytes = s7Plc.S7PlcRead("DB47.10", Convert.ToUInt16(1));
                    var getMaterial = Byte_BitToString(readBytes.Content);

                    conveyorReadData.GetAOne = getMaterial[0] == '1';
                    conveyorReadData.GetASeven = getMaterial[1] == '1';

                    #endregion

                    #region 读取PLC---B001 B007是否取完料
                    //判断出库口PLC是否放完料
                    readBytes = s7Plc.S7PlcRead("DB47.12", Convert.ToUInt16(1));
                    var getMaterialB = Byte_BitToString(readBytes.Content);
                    conveyorReadData.GetBOne = getMaterialB[0] == '1';
                    conveyorReadData.GetBSeven = getMaterialB[1] == '1';
                    #endregion

                    #region 读取前两个
                    var list = _SqlSugarDapper.DB.Queryable<Warehouse>().Where(w => w.WarehouseCode == "9001").OrderBy("layer").ToList();
                    int index1 = 2;
                    for (int i = 0; i < list.Count; i++)
                    {
                        var readBytess1 = s7Plc.S7PlcRead("DB47." + (322 + index1).ToString(), 1);
                        //var sdsd = "DB47." + (322 + index1).ToString();
                        var intos1 = Byte_BitToString(readBytess1.Content);

                        var good1 = intos1[0] == '1' ? 1 : 0;
                        var good2 = intos1[1] == '1' ? 1 : 0;

                        _SqlSugarDapper.DB.Updateable<Warehouse>()
                            .SetColumns(w => w.Goods1 == good1)
                            .SetColumns(w => w.Goods2 == good2)
                            .Where(w => w.WarehouseCode == "9001" && w.layer == list[i].layer)
                            .ExecuteCommand();
                        index1 += 2;
                    }
                    #endregion

                    #region 读取前两个
                    var list9002 = _SqlSugarDapper.DB.Queryable<Warehouse>().Where(w => w.WarehouseCode == "9002").OrderBy("layer").ToList();
                    foreach (var item in list9002)
                    {
                        var readBytess1 = s7Plc.S7PlcRead("DB47." + (322 + index1).ToString(), 1);
                        var intos1 = Byte_BitToString(readBytess1.Content);

                        var good1 = intos1[0] == '1' ? 1 : 0;
                        var good2 = intos1[1] == '1' ? 1 : 0;

                        _SqlSugarDapper.DB.Updateable<Warehouse>()
                            .SetColumns(w => w.Goods1 == good1)
                            .SetColumns(w => w.Goods2 == good2)
                            .Where(w => w.WarehouseCode == "9002" && w.layer == item.layer)
                            .ExecuteCommand();
                        index1 += 2;
                    }
                    #endregion

                    #region 处理输送线出库异常任务
                    //读到异常任务号
                    var abnormalTaskCode = s7Plc.S7PlcReadInt("DB47.364", 2).Content;

                    var subTask = _SqlSugarDapper.DB.Queryable<WcsTaskConveyor>()
                        //.Where(w => w.Sub_TaskCode == "7637")
                        .Where(w => w.Sub_TaskCode == abnormalTaskCode.ToString())
                        .First();
                    if (subTask != null)
                    {
                        var localtion = Warehouse.MaterialTypeOutPLCError(1, subTask.MaterialType, subTask.Start_Station);
                        if (localtion != null)
                        {
                            //找到一个可用库存
                            /*
                                把之前的托盘号状态改为55
                                更新任务信息  托盘号loc[0]   出库层数loc[0]  任务状态25
                                把当前准备出的托盘状态改为出库占用
                                */

                            string barCode = localtion[0].barCode;
                            string WMSBinCode = localtion[0].ID.Substring(5);
                            string Start_Station = localtion[0].ID.Substring(0, 4);
                            string End_Station = Start_Station == "9001" ? "B001" : "B007";
                            _SqlSugarDapper.DB.BeginTran();
                            try
                            {
                                //把之前的托盘号状态改为55 9001-7
                                _SqlSugarDapper.DB.Updateable<WarehouseInfo>()
                                    .SetColumns(w => w.state == 55)
                                    .Where(w => w.barCode == subTask.TrayBar_Code)
                                    .ExecuteCommand();

                                //更新子任务信息  托盘号loc[0]   出库层数loc[0]  任务状态25
                                _SqlSugarDapper.DB.Updateable<WcsTaskConveyor>()
                                    .SetColumns(w => w.TrayBar_Code == localtion[0].barCode)
                                    .SetColumns(w => w.WMSBinCode == WMSBinCode)
                                    .SetColumns(w => w.Task_State == 25)
                                    .SetColumns(w => w.Start_Station == Start_Station)
                                    .SetColumns(w => w.Current_Station == Start_Station)
                                    .SetColumns(w => w.End_Station == End_Station)
                                    .Where(w => w.Sub_TaskCode == subTask.Sub_TaskCode)
                                    .ExecuteCommand();

                                //更新主任务信息 
                                _SqlSugarDapper.DB.Updateable<WcsTaskMain>()
                                    .SetColumns(w => w.TrayBar_Code == barCode)
                                    .SetColumns(w => w.StartWMSBinCode == WMSBinCode)
                                    .SetColumns(w => w.Start_Station == Start_Station)
                                    .SetColumns(w => w.Current_Station == Start_Station)
                                    .SetColumns(w => w.StartWMSBinCode == WMSBinCode)
                                    .SetColumns(w => w.End_Station == End_Station)
                                    .Where(w => w.Task_Code == subTask.Task_Code)
                                    .ExecuteCommand();
                                _SqlSugarDapper.DB.CommitTran();

                                //把当前准备出的托盘状态改为出库占用
                                WarehouseInfo.ChangeWarehouseInfo(localtion[0], (int)StationState.出库占用);

                                RunLog.runLog.Warning($@"【输送线任务模块】异常任务号【{abnormalTaskCode}】异常托盘码【{subTask.TrayBar_Code}】重新下发托盘码【{localtion[0].barCode}】");
                                //返回PLC 异常任务收到信号
                                s7Plc.S7PlcWiterBool("DB48.22.0", (bool)true);
                            }
                            catch (Exception)
                            {
                                _SqlSugarDapper.DB.RollbackTran();
                            }
                        }
                    }

                    #endregion

                    #region 读取PLC报警信息
                    foreach (var item in plcErrors)
                    {
                        if (s7Plc.S7PlcReadBool("DB47." + item.PlcAddress).Content)
                        {
                            _SqlSugarDapper.DB.Updateable<WcsDevPlc>()
                                .SetColumns(a => a.Remark == item.PlcErrorName)
                                .Where(w => w.PLC_Name == "铸造区").ExecuteCommand();

                            var _plcErrorName = _SqlSugarDapper.DB.SqlQueryable<PLCErrorRecord>($"SELECT *, DATEDIFF( MINUTE, PlcErrorTime, GETDATE( ) ) AS dataIff FROM PLCErrorRecord").Where(w => w.PlcErrorName == $"{item.PlcErrorName}").OrderBy("PlcErrorTime DESC").First();

                            if (_plcErrorName == null || _plcErrorName.dataIff >= 30)
                            {
                                _SqlSugarDapper.DB.Insertable(new PLCErrorRecord
                                {
                                    PlcErrorName = item.PlcErrorName,
                                    PlcErrorTime = System.DateTime.Now
                                }).ExecuteCommand();
                            }

                            break;
                        }
                        else if (!_flag)
                        {
                            _SqlSugarDapper.DB.Updateable<WcsDevPlc>()
                               .SetColumns(a => a.Remark == "")
                               .Where(w => w.PLC_Name == "铸造区").ExecuteCommand();
                        }
                    }

                    #endregion

                    Thread.Sleep(1000);
                }
            }
            catch (Exception ex)
            {
                RunLog.runLog.Error($@"{_modular}异常信息【{ex.Message}】【{ex.StackTrace}】");
            }
        }

        /// <summary>
        /// 给PLC写入数据
        /// </summary>
        /// <returns></returns>
        public bool WriteData(WcsDevStation wcsDevStation, string address, byte data)
        {
            try
            {
                //仿真模式直接返回成功
                if (_simulation == "1")
                {
                    return true;
                }
                wcsDevStation.S7Plc = s7Plc;

                byte[] bytes = new byte[2];
                bytes[0] = (byte)data;

                var result = s7Plc.S7PlcWiter(address, bytes);

                if (!result.IsSuccess)
                {
                    RunLog.runLog.Debug($@"{_modular}给站台【{wcsDevStation.Station_Plc_No}】下发任务失败，失败原因：【{result.Message}】");
                    return false;
                }
                RunLog.runLog.Debug($@"{_modular}给站台【{wcsDevStation.Station_Plc_No}】下发任务成功，下发位置【{data}】");
                return true;
            }
            catch (Exception ex)
            {
                RunLog.runLog.Error($@"{_modular}异常信息【{ex.Message}】【{ex.StackTrace}】");
                return false;
            }
        }

        /// <summary>
        /// 给PLC写入数据
        /// </summary>
        /// <returns></returns>
        public bool WriteDataa(string warehousecode, byte data)
        {
            try
            {
                //仿真模式直接返回成功
                if (_simulation == "1")
                {
                    return true;
                }
                //var result = PlcManeger.Write(address, data);

                //if (!result.IsSuccess)
                //{
                //    RunLog.runLog.Debug($@"{_modular}给站台【{warehousecode}】下发任务失败，失败原因：【{result.Message}】");
                //    return false;
                //}
                return true;
            }
            catch (Exception ex)
            {
                RunLog.runLog.Error($@"{_modular}异常信息【{ex.Message}】【{ex.StackTrace}】");
                return false;
            }
        }

        /// <summary>
        /// 根据站台找到所属PLC
        /// </summary>
        public object GetStationNo(string StationNo)
        {
            foreach (var plcDev in wcsDevPlcList)
            {
                if (plcDev.stackerStation.Station_Plc_No == StationNo)
                {
                    plcDev.WritePlcManager = plcDev.stackerStation;
                    return plcDev.stackerStation;
                }
                foreach (var conveyStation in plcDev.conveyStations)
                {
                    if (conveyStation.Station_Plc_No == StationNo)
                    {
                        plcDev.conveyStation = conveyStation;
                        plcDev.WritePlcManager = conveyStation;

                        return conveyStation;
                    }
                }
            }
            return null;
        }

        /// <summary>
        /// 校验库存条码
        /// </summary>
        public bool VerifyBarcode(string barCode)
        {
            var codeList = _SqlSugarDapper.DB.Queryable<WarehouseInfo>().Where(w => w.barCode == barCode).First();
            var wcsmain = _SqlSugarDapper.DB.Queryable<WcsTaskMain>().Where(w => w.TrayBar_Code == barCode && (w.Start_Station == "A002" || w.Start_Station == "A006")).First();
            if (codeList == null && wcsmain == null)
            {
                return true;
            }
            else
            {
                return false;
            }
        }

    }

    public class MesData
    {
        /// <summary>
        /// 用于标识上传数据唯一，防止重复请求
        /// </summary>
        public string uuid { get; set; }

        /// <summary>
        /// 用于标识当前数据是否仅为测试数据。Default false
        /// </summary>
        public bool debug { get; set; }

        /// <summary>
        /// unix时间戳, 以秒为单位;数据上传的时间
        /// </summary>
        public long uploadTime { get; set; }

        /// <summary>
        /// 设备唯一编码
        /// </summary>
        public string machineId { get; set; }

        /// <summary>
        /// 数据列表
        /// </summary>
        public List<DataList> dataList { get; set; }
    }


    public class DataList
    {
        /// <summary>
        /// 参数编码
        /// </summary>
        public string param { get; set; }

        /// <summary>
        /// 采集值
        /// </summary>
        public string value { get; set; }

        /// <summary>
        /// 采集时间
        /// </summary>
        public long collectionTime { get; set; }

        /// <summary>
        /// 采集点位
        /// </summary>
        public string gatherSpot { get; set; }
    }
}
